package org.yu.api.register.data;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.SpawnEggItem;
import net.minecraftforge.client.IItemRenderProperties;
import net.minecraftforge.client.RenderProperties;
import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.yu.Yu;
import org.yu.api.register.ItemHolder;


import javax.annotation.Nonnull;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;

public class LazyItemModelProvider extends ItemModelProvider {
    private static final ResourceLocation SPECIAL_BLOCK_PARENT = new ResourceLocation(Yu.MODID, "item/base/special_block");
    private static final ResourceLocation SPAWN_EGG_PARENT = new ResourceLocation("minecraft", "item/template_spawn_egg");
    private final Map<ItemHolder<?>, BiConsumer<ItemModelProvider, ItemHolder<?>>> iItemModelMap;
    private final String modid;
    private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
    public LazyItemModelProvider(DataGenerator generator, String modid, ExistingFileHelper fileHelper, Map<ItemHolder<?>, BiConsumer<ItemModelProvider, ItemHolder<?>>> iItemModelMap) {
        super(generator, modid, fileHelper);
        this.iItemModelMap = iItemModelMap;
        this.modid = modid;
    }

    private static boolean isItemStackRenderer(Item item) {
        try {
            IItemRenderProperties properties = RenderProperties.get(item);
            if (properties != IItemRenderProperties.DUMMY) {
                properties.getItemStackRenderer();
            } else {
                // Forge no longer calls this during datagen
                // so we need to do it manually
                AtomicReference<IItemRenderProperties> ref = new AtomicReference<>(null);
                item.initializeClient(ref::set);
                properties = ref.get();
                if (properties != null) properties.getItemStackRenderer();
            }
        } catch (RuntimeException e) {
            return true;
        } catch (Exception | NoClassDefFoundError e) {
            return false;
        }
        return false;
    }

    @Override
    protected void registerModels() {
        iItemModelMap.forEach((itemHolder, iItemModel) -> {
            var item = itemHolder.get();
            var id = item.getRegistryName();
            if (isItemStackRenderer(itemHolder.get())) {
                this.getBuilder(itemHolder.get().getRegistryName().getPath()).parent(new ModelFile.ExistingModelFile(SPECIAL_BLOCK_PARENT, existingFileHelper));
            } else if (item instanceof SpawnEggItem) {
                this.withExistingParent(id.getPath(), SPAWN_EGG_PARENT);
            } else {
                iItemModel.accept(this, itemHolder);
            }
        });
    }
    @Nonnull
    @Override
    public String getName() {
        return "LazyItemModelProvider For" + modid;
    }
}
